<?php
declare (strict_types = 1);

namespace app\tools;

use app\exception\LogicException;
use app\facade\CurlFacade;
use Exception;
use think\App;

final class OpenTool
{
    private $appID;
    private $secret;

    private $url = "https://api.weixin.qq.com";

    /**
     * WechatTool constructor.
     * @throws Exception
     */
    public function __construct()
    {
        $this->appID = config('wechat.open_app_id');
        $this->secret = config('wechat.open_app_secret');
    }

    /**
     * 获取&缓存access_token
     *
     * @return mixed|object|App
     * @throws Exception
     */
    // public function getAccessToken()
    // {
    //     if (cache('applet_access_token')) {
    //         return cache('applet_access_token');
    //     } else {
    //         $url = "$this->url/cgi-bin/token?grant_type=client_credential&appid=$this->appID&secret=$this->secret";
    //         $response = json_decode(CurlFacade::curlGET($url), true);
    //
    //         if (isset($response['errcode']) && 0 != $response['errcode']) {
    //             throw new LogicException($response['errmsg'], $response['errcode']);
    //         }
    //
    //         cache("cache('applet_access_token')", $response['access_token'], [
    //             // 'expire' => $response['expires_in']
    //             'expire' => 5400
    //         ]);
    //
    //         return $response['access_token'];
    //     }
    // }

    /**
     * 通过 code 获取 access_token
     *
     * @param $code
     * @return mixed
     * @throws LogicException
     */
    public function code2Session($code)
    {
        $url = "$this->url/sns/oauth2/access_token?appid=$this->appID&secret=$this->secret&code=$code&grant_type=authorization_code";
        $response = json_decode(CurlFacade::curlGET($url), true);

        if (isset($response['errcode']) && 0 != $response['errcode']) {
            throw new LogicException($response['errmsg'], $response['errcode']);
        }

        // 缓存一下
        $accessTokenCacheKey = 'access_token_cache_key_' . $response['openid'];
        $refreshTokenCacheKey = 'refresh_token_cache_key_' . $response['openid'];
        cache($accessTokenCacheKey, $response['access_token'], [
            'expire' => 7000
        ]);
        cache($refreshTokenCacheKey, $response['refresh_token'], [
            'expire' => 2592000
        ]);

        return $response;
    }

    /**
     * 获取可用access token
     *
     * @param $openid
     * @return mixed|object|App
     * @throws LogicException
     */
    public function getAccessTokenByOpenid($openid)
    {
        $accessTokenCacheKey = 'access_token_cache_key_' . $openid;
        $refreshTokenCacheKey = 'refresh_token_cache_key_' . $openid;
        if ($accessToken = cache($accessTokenCacheKey)) {
            return $accessToken;
        }

        if ($refreshToken = cache($refreshTokenCacheKey)) {
            $url = "$this->url/sns/oauth2/refresh_token?appid=$this->appID&refresh_token=$refreshToken&grant_type=refresh_token";
            $response = json_decode(CurlFacade::curlGET($url), true);

            if (isset($response['errcode']) && 0 != $response['errcode']) {
                throw new LogicException($response['errmsg'], $response['errcode']);
            }
            cache($accessTokenCacheKey, $response['access_token'], [
                'expire' => 7000
            ]);
            return $response['access_token'];
        }

        throw new LogicException('需要微信重新授权');
    }

    /**
     * 获取用户信息
     *
     * @param $openid
     * @return mixed
     * @throws LogicException
     */
    public function userinfo($openid)
    {
        $accessToken = $this->getAccessTokenByOpenid($openid);
        $url = "$this->url/sns/userinfo?access_token=$accessToken&openid=$openid";
        $response = json_decode(CurlFacade::curlGET($url), true);
        if (isset($response['errcode']) && 0 != $response['errcode']) {
            throw new LogicException($response['errmsg'], $response['errcode']);
        }

        return $response;
    }
}
